#include "OSSInfo.h"
#include "Misc/Paths.h"
#include "GenericPlatform/GenericPlatformHttp.h"


bool FAliyunOssTaskInfo::UseBucketNameAndKey()const
{
	return useBucketNameAndKey;
}

FAliyunOssTaskInfo::FAliyunOssTaskInfo(const EAliyunOssType& type, const FString& bucket, const FString& key
	, TArray<uint8>* LocalBuffer)
	:useBucketNameAndKey(true),handleType(type), bucketName(bucket), objectKey(key)
	, strLocalObjectFilePath(), LocalObjectDataPtr(LocalBuffer)
{


}



FAliyunOssTaskInfo::FAliyunOssTaskInfo(const EAliyunOssType& type, const FString& completefilePath, TArray<uint8>* LocalBuffer)
	:useBucketNameAndKey(false), handleType(type), inOssObjectFilePath(TransformationPath(completefilePath))
	, strLocalObjectFilePath(), LocalObjectDataPtr(LocalBuffer)
{
	FAliyunOssTaskInfo::TransformationPathToBucketAndKey(inOssObjectFilePath, bucketName, objectKey);
}


//FAliyunOssTaskInfo::FAliyunOssTaskInfo(const EAliyunOssType& type, const FString& bucket, const FString& key
//	, const FString& completefilePath,TArray<uint8>* LocalBuffer)
//	:handleType(type), bucketName(bucket), objectKey(key)
//	, inOssObjectFilePath(TransformationPath(completefilePath))
//	, strLocalObjectFilePath(), LocalObjectDataPtr(LocalBuffer)
//{
//	FString bName, bkey;
//	if (FAliyunOssTaskInfo::TransformationPathToBucketAndKey(inOssObjectFilePath, bName, bkey))
//	{
//		if (bucketName.Len() <= 1)bucketName = bName;
//		if (objectKey.Len() <= 3)objectKey = key;
//	}
//}

FAliyunOssTaskInfo::FAliyunOssTaskInfo(const EAliyunOssType& type, const FString& bucket, const FString& key
	,const FString& LocalObjectFilePath)
	:useBucketNameAndKey(true), handleType(type), bucketName(bucket), objectKey(key)
	, strLocalObjectFilePath(LocalObjectFilePath), LocalObjectDataPtr(nullptr)
{


}



FAliyunOssTaskInfo::FAliyunOssTaskInfo(const EAliyunOssType& type, const FString& completefilePath
	, const FString& LocalObjectFilePath)
	:useBucketNameAndKey(false), handleType(type), inOssObjectFilePath(TransformationPath(completefilePath))
	, strLocalObjectFilePath(LocalObjectFilePath), LocalObjectDataPtr(nullptr)
{
	FAliyunOssTaskInfo::TransformationPathToBucketAndKey(inOssObjectFilePath, bucketName, objectKey);
}


FAliyunOssTaskInfo::FAliyunOssTaskInfo(const EAliyunOssType& type, const FString& bucket, const FString& key
	, const FString& completefilePath, const FString&  LocalObjectFilePath)
	:useBucketNameAndKey(true), handleType(type), bucketName(bucket), objectKey(key)
	, inOssObjectFilePath(TransformationPath(completefilePath))
	, strLocalObjectFilePath(LocalObjectFilePath), LocalObjectDataPtr(nullptr)
{
	FString bName, bkey;
	if (FAliyunOssTaskInfo::TransformationPathToBucketAndKey(inOssObjectFilePath, bName, bkey))
	{
		if (bucketName.Len() <= 1)bucketName = bName;
		if (objectKey.Len() <= 3)objectKey = key;
	}
}

//build EAliyunOssType::UploadBufferData taskinfo
FAliyunOssTaskInfo::FAliyunOssTaskInfo(const FString& bucket, const FString& key
	, const FString& completefilePath, const FString& InContentData)
	:handleType(EAliyunOssType::UploadStringBuffer), bucketName(bucket), objectKey(key)
	, inOssObjectFilePath(TransformationPath(completefilePath))
	, strLocalObjectFilePath(InContentData), LocalObjectDataPtr(nullptr)
{

}

bool FAliyunOssTaskInfo::IsValid()const
{
	if (LocalObjectDataPtr == nullptr&&strLocalObjectFilePath.Len() <= 3) 
	{
		return false;
	}
	return  bucketName.Len()*objectKey.Len() > 3 || inOssObjectFilePath.Len() > 3;
}


FString FAliyunOssTaskInfo::GetOssObjPath()const
{	
	return objectKey.Len() > inOssObjectFilePath.Len() ? objectKey : inOssObjectFilePath;
}


FString FAliyunOssTaskInfo::TransformationPath(const FString& path)
{
	if (path.Len() <= 4)return "";
	FString strPath = FPaths::GetPath(path);
	FString strBaseFilename = FPaths::GetBaseFilename(path);
	FString strExtension = FPaths::GetExtension(path, true);
	FString strBaseFilenameEncode = FGenericPlatformHttp::UrlEncode(strBaseFilename);
	return FString::Printf(L"%s/%s%s", *strPath, *strBaseFilenameEncode, *strExtension);
}



bool FAliyunOssTaskInfo::TransformationPathToBucketAndKey(const FString& path, FString& Bucket, FString& key)
{
	if (path.Len() >= 19)//  Minimum length is ""*.aliyuncs.com/*.*" = 19
	{
		FString ObjectBasePath;
		if (!path.Split(TEXT(".aliyuncs.com/"), &ObjectBasePath, &key, ESearchCase::CaseSensitive)) 
		{
			return false;
		}
		FString temp;
		if (ObjectBasePath.Split(TEXT("//"), nullptr, &temp, ESearchCase::CaseSensitive))
		{
			if (!temp.Split(TEXT("."), &Bucket, nullptr, ESearchCase::CaseSensitive))
			{
				return false;
			}
			return Bucket.Len()*key.Len() >= 3;//  Minimum length is "*.*" = 3
		}
	}
	return false;
}




void FOssCallBackFunction::CallOnProgress(float fPercent, void* userData)const
{
	onProgress.ExecuteIfBound(fPercent, userData);
	
}

void FOssCallBackFunction::CallOnComplete(bool isSuccess, void* userData, const FString& msg)const
{
	onCompleteWithMsg.ExecuteIfBound(isSuccess, userData, msg);
	onComplete.ExecuteIfBound(isSuccess, userData);
}

void FOssCallBackFunction::CallOnComplete(bool isSuccess, void* userData) const
{
	onComplete.ExecuteIfBound(isSuccess, userData);
	onCompleteWithMsg.ExecuteIfBound(isSuccess, userData,"");	
}




FOssTimeTakeNotes::FOssTimeTakeNotes()
	:dataSize(0), buildTime(FDateTime::Now()), loadSeep(0)
{
	
}
void FOssTimeTakeNotes::StartWork(int64 size)
{
	startTime = FDateTime::Now();
	dataSize = FMath::Max(size, dataSize);
}


void FOssTimeTakeNotes::CompleteWork(int64 size)
{
	completeTime = FDateTime::Now();
	dataSize = FMath::Max(size, dataSize );
	float t = (completeTime - startTime).GetTotalSeconds();
	if (dataSize > 0 && t > 0) 
	{
		loadSeep = GetSizeUintMb() / t;
	}
	else {
		loadSeep = 0;
	}
}

float FOssTimeTakeNotes::GetSizeUintMb()const 
{
	return float((double)dataSize / 1048576.0f);
}

FString FOssTimeTakeNotes::ToString() const
{
	return FString::Printf(TEXT("(dateSize=%0.2fMb,Time use =%0.2f s,Seep = %0.2f MB/S )")
		, GetSizeUintMb(), (completeTime - startTime).GetTotalSeconds(), loadSeep);
}